﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace WFL.Windows.Forms.Theme
{
    public class Style
    {
        private string _name;
        public string Name
        {
            get { return _name; }
        }

        private IDictionary<string, string> _properties;
        public IDictionary<string, string> Properties
        {
            get { return _properties; }
        }

        private SkinBase _skin;
        public SkinBase Skin
        {
            get { return _skin; }
            internal set { _skin = value; }
        }

        public Style(string name, IDictionary<string, string> properties)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            _name = name;
            _properties = properties;
        }

        public void Apply(object obj)
        {
            if (obj == null
                || _properties == null)
            {
                return;
            }

            //特殊属性处理
            Control ctrl = obj as Control;
            if (ctrl != null)
            {
                if (ctrl is Form)
                {
                    //顶级窗体
                    _properties.Remove("Dock");
                    _properties.Remove("Anchor");
                    _properties.Remove("Margin");
                }
                else
                { 
                    //控件
                    //处理Anchor属性，若同时存在Anchor、Dock，则Dock优先
                    if (_properties.ContainsKey("Anchor"))
                    {
                        if (!_properties.ContainsKey("Dock"))
                        {
                            ctrl.Anchor = GetValue<AnchorStyles>("Anchor");
                            if ((ctrl.Anchor & AnchorStyles.Right) == AnchorStyles.Right)
                            {
                                if (_properties.ContainsKey("Right"))
                                {
                                    if (ctrl.Parent != null)
                                    {
                                        int left;
                                        Point location;
                                        Rectangle bounds;
                                        if (GetValue<int>("Left", out left))
                                        {

                                        }
                                        else if (GetValue<Point>("Location", out location))
                                        {
                                            left = location.X;
                                        }
                                        else if (GetValue<Rectangle>("Bounds", out bounds))
                                        {
                                            left = bounds.Left;
                                        }
                                        else
                                        {
                                            left = ctrl.Left;
                                        }
                                        ctrl.Width = ctrl.Parent.ClientSize.Width - left - GetValue<int>("Right");
                                    }
                                    _properties.Remove("Right");
                                }
                            }
                            if ((ctrl.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom)
                            {
                                if (_properties.ContainsKey("Bottom"))
                                {
                                    if (ctrl.Parent != null)
                                    {
                                        int top;
                                        Point location;
                                        Rectangle bounds;
                                        if (GetValue<int>("Top", out top))
                                        {

                                        }
                                        else if (GetValue<Point>("Location", out location))
                                        {
                                            top = location.Y;
                                        }
                                        else if (GetValue<Rectangle>("Bounds", out bounds))
                                        {
                                            top = bounds.Top;
                                        }
                                        else
                                        {
                                            top = ctrl.Top;
                                        }
                                        ctrl.Height = ctrl.Parent.ClientSize.Height - top - GetValue<int>("Bottom");
                                    }
                                    _properties.Remove("Bottom");
                                }
                            }
                        }
                        _properties.Remove("Anchor");
                    }
                }
            }
            //反射设置属性
            Type objType = obj.GetType();
            foreach (KeyValuePair<string, string> pair in _properties)
            {
                string propName = pair.Key;
                PropertyInfo objProp = objType.GetProperty(propName);
                if (objProp != null &&
                    objProp.CanWrite)
                {
                    Type targetType = objProp.PropertyType;
                    object result = null;
                    bool succeeded = GetValue(propName, targetType, out result);
                    //默认情况下，放弃设置转换失败的属性
                    if (succeeded)
                    {
                        objProp.SetValue(obj, result, null);
                    }
                }
            }
        }

        public bool GetValue(string name, Type targetType, out object value)
        {
            value = null;
            bool succeeded = false;
            if (_properties.ContainsKey(name))
            {
                object result = null;
                succeeded = Skin.ChangeType(_properties[name], targetType, out result);
                if (succeeded)
                {
                    value = result;
                }
                else
                {
                    throw new InvalidCastException("无法转换到指定的类型。");
                }
            }
            return succeeded;
        }

        public bool GetValue<T>(string name, out T value)
        {
            value = default(T);
            object result = null;
            bool succeeded = GetValue(name, typeof(T), out result);
            if (succeeded)
            {
                value = (T)result;
            }
            return succeeded;
        }

        public object GetValue(string name, Type targetType)
        {
            object result = null;
            GetValue(name, targetType, out result);
            return result;
        }

        public T GetValue<T>(string name)
        {
            T result = default(T);
            GetValue<T>(name, out result);
            return result;
        }


    }
}
